package com.mayn.api;

import java.rmi.RemoteException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.rpc.ServiceException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sf.integration.expressservice.service.CommonServiceServiceLocator;
import com.sf.integration.expressservice.service.IService;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.xml.XMLSerializer;

/**
 * 顺丰API接口，使用宁美APPKEY
 * 
 * @author Administrator
 *
 */
public class SFApi {

	private static final Logger log = LoggerFactory.getLogger(SFApi.class);

	public static String sf_appid = "0273550057";
	public static String sf_appkey = "TrHu_UbV3Rx02Fb[A6~Rz_BqwS-V~-9}";

	public static String url = "http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService";
	/*
	 * IP访问URL String url = "http://219.134.187.221/bsp-oisp/ws/expressService";
	 */

	public static void main(String[] args) throws Exception {
		String retValue = "";
		/*
		 * //问题件1 
		 * retValue = getSfTraceByApi("973898942040"); 
		 * //问题件2 
		 * retValue = getSfTraceByApi("973556610133"); 
		 * //待自取 
		 * retValue = getSfTraceByApi("973844184684"); 
		 * retValue = getSfTraceByApi("973882664128");
		 */
		// retValue = getSfTraceByApi("973913227992");

		// retValue = getSfTraceByApi("972280924025");

		// retValue = getSfTraceByApi("972036657532");
		// 派送不成功
		// retValue = getSfTraceByApi("972021099612");

		// 拒收件
		// retValue = getSfTraceByApi("972506588781");

		// 快件领取成功
		retValue = getSfTraceByApi("972646987165");
		log.info(retValue);

		// 快递柜
		retValue = getSfTraceByApi("972679819178");
		log.info(retValue);
		//
		retValue = getSfTraceByApi("612409810365");

		log.info(retValue);
	}

	public static String getSfTraceJson(String LogisticCode) {
		return getSfTraceByApi(LogisticCode);
	}
	
	public static String getSfTraceByApi(String LogisticCode) {
		String traceXml = getSfTraceXml(LogisticCode);
		String jsonStr = ConvertXMLtoJSON(traceXml);
		try {
			JSONObject jo = JSONObject.fromObject(jsonStr);
			JSONObject newJson = new JSONObject();
			if (jo.containsKey("Head")) {
				if (jo.getString("Head").equals("OK")) {
					newJson.put("LogisticCode", LogisticCode);
					newJson.put("ShipperCode", "SF");
					newJson.put("Success", "true");
					if (!jo.getString("Body").equals("[]")) {
						if (jo.getJSONObject("Body").containsKey("RouteResponse")) {
							JSONArray traceJson = new JSONArray();
							if (jo.getJSONObject("Body").getJSONObject("RouteResponse").getString("Route").startsWith("[")) {
								JSONArray oldTrace = jo.getJSONObject("Body").getJSONObject("RouteResponse").getJSONArray("Route");
								if (oldTrace.size() > 0) {
									for (int i = 0; i < oldTrace.size(); i++) {
										JSONObject joItem = new JSONObject();
										if (oldTrace.getJSONObject(i).containsKey("@remark")) {
											joItem.put("AcceptStation", oldTrace.getJSONObject(i).getString("@remark"));
										} else {
											joItem.put("AcceptStation", "");
										}
										joItem.put("AcceptTime", oldTrace.getJSONObject(i).getString("@accept_time"));
										joItem.put("Remark", oldTrace.getJSONObject(i).getString("@opcode"));

										// 删除一些无效路由，参考单号972280924025
										if (i == oldTrace.size() - 1) {
											if (oldTrace.getJSONObject(i).containsKey("@remark")) {
												traceJson.add(joItem);
											} else {
												log.debug("发现无效路由");
											}
										} else {
											if (oldTrace.getJSONObject(i).containsKey("@remark") || oldTrace.getJSONObject(i + 1).containsKey("@remark")) {
												traceJson.add(joItem);
											} else {
												log.debug("发现无效路由");
											}
										}
									}
									String remark = traceJson.getJSONObject(traceJson.size() - 1).getString("AcceptStation");
									String opcode = traceJson.getJSONObject(traceJson.size() - 1).getString("Remark");
									String accept_time = traceJson.getJSONObject(traceJson.size() - 1).getString("AcceptTime");
									// 已签收
									if (remark.contains("已签收")) {
										newJson.put("State", 3);
									}
									// 根据路由码可以明确判断为问题件
									else if (checkErrorRouteCode(opcode)) {
										newJson.put("State", 4);
									}
									// 根据路由码结合最近一次路由时间可以明确判断为问题件
									else if (checkErrorRouteCode(opcode, accept_time)) {
										newJson.put("State", 4);
									}
									// 待自取问题件
									else if (!checkErrorRouteRemark(remark, accept_time)) {
										newJson.put("State", 4);
									}
									// 其他问题件
									else if (!checkErrorRouteRemark(remark)) {
										newJson.put("State", 4);
									}
									// 已签收状态码
									else if (checkSignRouteCode(opcode)) {
										newJson.put("State", 3);
									}
									// 其它默认在途
									else {
										newJson.put("State", 2);
									}
									newJson.put("Traces", traceJson);
								} else {
									newJson.put("Traces", "[]");
								}
							} else {
								JSONObject oldTrace = jo.getJSONObject("Body").getJSONObject("RouteResponse").getJSONObject("Route");
								JSONObject joItem = new JSONObject();
								traceJson = new JSONArray();
								if (oldTrace.containsKey("@remark")) {
									joItem.put("AcceptStation", oldTrace.getString("@remark"));
								} else {
									joItem.put("AcceptStation", "");
								}
								joItem.put("AcceptTime", oldTrace.getString("@accept_time"));

								joItem.put("Remark", oldTrace.getString("@opcode"));
								traceJson.add(joItem);
								String remark = oldTrace.getString("@remark");
								// 已签收
								if (remark.contains("已签收")) {
									newJson.put("State", 3);
								}
								// 问题件
								else if (!checkErrorRouteRemark(remark)) {
									newJson.put("State", 4);
								} else {
									newJson.put("State", 2);
								}
								newJson.put("Traces", traceJson);
							}
						}
					} else {
						newJson.put("Traces", "[]");
					}
				} else {
					newJson.put("Success", "false");
				}
				return newJson.toString();
			}
		} catch (Exception e) {
			log.error(e.getMessage());
			log.error("xml:" + traceXml);
			log.error("json:" + jsonStr);
		}
		return "{}";
	}

	/**
	 * 判断描述和时间判断是否待自取等问题件
	 * 
	 * @param remark
	 * @param accept_time
	 * @return
	 */
	public static Boolean checkErrorRouteRemark(String remark, String accept_time) {
		if (remark == null || remark.equals("") || accept_time == null || accept_time.equals("")) {
			return false;
		}
		if (remark.contains("待自取") || remark.contains("派送不成功")) {
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date dateC = null;
			try {
				dateC = formatter.parse(accept_time);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Date dateN = new Date();
			long diff = dateN.getTime() - dateC.getTime();
			long days = diff / (1000 * 60 * 60 * 24);
			// 大于7天
			if (days > 7) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 判断描述判断是问题件
	 * 
	 * @param remark
	 * @return
	 */
	public static Boolean checkErrorRouteRemark(String remark) {
		if (remark == null || remark.equals("")) {
			return false;
		}
		if (remark.contains("转寄")) {
			return false;
		}
		if (remark.contains("退回")) {
			return false;
		}
		return true;
	}

	/**
	 * 单独根据opcode判断是否问题件 参考顺丰给出路由参考码，以下是明确为问题件的路由 70 客户要求自取快件,待自取
	 * 有比较多的原因，不同的原因描述不同 99 快件已退回/转寄 631 快件已退回 627 快件转寄XXX 单号OOO
	 * 
	 * @param opcode
	 * @return
	 */
	public static Boolean checkErrorRouteCode(String opcode) {
		if (opcode == null || opcode.equals("")) {
			return false;
		}
		if (opcode.equals("70") || opcode.equals("99") || opcode.equals("631")) {
			return true;
		}
		return false;
	}

	/**
	 * 单独根据opcode判断是否问题件 参考顺丰给出路由参考码，以下是可能派送不成功的路由 33 快件派送不成功（原因：XXX），已送返
	 * XXXX服务点
	 * 
	 * @param opcode
	 * @return
	 */
	public static Boolean checkErrorRouteCode(String opcode, String accept_time) {
		if (opcode == null || opcode.equals("")) {
			return false;
		}
		if (accept_time == null || accept_time.equals("")) {
			return false;
		}
		if (opcode.equals("33") || opcode.equals("34") || opcode.equals("634") || opcode.equals("44")) {
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date dateC = null;
			try {
				dateC = formatter.parse(accept_time);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			Date dateN = new Date();
			long diff = dateN.getTime() - dateC.getTime();
			long days = diff / (1000 * 60 * 60 * 24);
			// 大于7天
			if (days > 7) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 根据opcode判断是否签收
	 * 
	 * @param opcode
	 * @return
	 */
	public static Boolean checkSignRouteCode(String opcode) {
		if (opcode == null || opcode.equals("")) {
			return false;
		}
		if (opcode.equals("8000")) {
			return true;
		}
		if (opcode.equals("80")) {
			return true;
		}
		// 派件成功
		if (opcode.equals("658")) {
			return true;
		}
		// 快递柜自取
		if (opcode.equals("125")) {
			return true;
		}

		return false;
	}

	public static String getSfTraceXml(String LogisticCode) {
		try {
			String xmlStr = GetXml(LogisticCode);
			String soapRequestData = toSoapString(xmlStr);
			// System.out.println(soapRequestData);
			CommonServiceServiceLocator service = new CommonServiceServiceLocator();
			IService client;
			client = service.getCommonServicePort();
			String retValue = client.sfexpressService(soapRequestData);
			return retValue;
		} catch (ServiceException | RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}

	public static String ConvertXMLtoJSON(String xml) {
		try {
			XMLSerializer xmlSerializer = new XMLSerializer();
			JSON json = xmlSerializer.read(xml);
			return json.toString(1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static String GetXml(String tracking_number) {
		StringBuffer sbXml = new StringBuffer();
		sbXml.append("<Request service=\"RouteService\" lang=\"zh-CN\">");
		sbXml.append("<Head>" + sf_appid + "," + sf_appkey + "</Head><Body>");
		sbXml.append("<RouteRequest tracking_type=\"1\" method_type=\"1\"");
		sbXml.append(" tracking_number=\"" + tracking_number + "\"/> ");
		sbXml.append("</Body> ");
		sbXml.append("</Request>");
		return sbXml.toString();
	}

	public static String toSoapString(String xmlStr) {
		StringBuilder _xmlstr = new StringBuilder();
		_xmlstr.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
		_xmlstr.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">");
		_xmlstr.append("<soap:Body><sfexpressService xmlns=\"http://service.expressservice.integration.sf.com/\"><arg0 xmlns=\"\">");
		_xmlstr.append(xmlStr);
		_xmlstr.append("</arg0></sfexpressService></soap:Body>");
		_xmlstr.append("</soap:Envelope>");
		return _xmlstr.toString();
	}
}